package wordctrl

import (
	"context"
	"fmt"
	"rewords-server-2024/internal/model/outin"
	"rewords-server-2024/utility/ufun"

	"go.mongodb.org/mongo-driver/bson"

	"rewords-server-2024/internal/model/input/form"
	"rewords-server-2024/utility/ztime"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"

	wordAPI "rewords-server-2024/api/word"
	"rewords-server-2024/internal/consts"
	"rewords-server-2024/internal/library/ecode"
	"rewords-server-2024/internal/model/entity"
	"rewords-server-2024/internal/model/input/query_in"
	"rewords-server-2024/internal/service"
)

type cBookCtrl struct{}

var BookCtrl = new(cBookCtrl)

// QueryList 获取词书列表
func (c *cBookCtrl) QueryList(ctx context.Context, req *wordAPI.BooksListReq) (res *wordAPI.BooksListRes, err error) {
	query, skip, limit, sort, _ := query_in.BuildMongoQueryWithPage(req.Conditions, req.OrderFields, req.Page, nil)
	g.Log().Debug(ctx, "MongoDB query conditions:", query)
	g.Log().Debug(ctx, "Skip:", skip, "Limit:", limit)

	// 查询数据
	result, err := service.Mgx().Find(ctx, consts.CWordBooks, query, nil, skip, limit, sort)
	if err != nil {
		return nil, gerror.Wrap(err, "获取数据失败")
	}

	var data []entity.WordBook
	if err = gconv.Struct(result, &data); err != nil {
		return nil, gerror.Wrap(err, "数据转换失败")
	}

	var total int64
	if req.Page.QueryCount {
		total, err = service.Mgx().CountDocuments(ctx, consts.CWordBooks, query)
		if err != nil {
			return nil, gerror.Wrap(err, "获取总数失败")
		}
	}

	res = &wordAPI.BooksListRes{
		List: ufun.If(len(data) > 0, data, []entity.WordBook{}),
		PageResult: query_in.PageResult{
			Current:  (skip / limit) + 1,
			PageSize: limit,
			Total:    total,
			Pages:    (total + limit - 1) / limit,
			HasNext:  (skip + limit) < total,
		},
	}
	return
}

// AddBook 添加词书
func (c *cBookCtrl) AddBook(ctx context.Context, req *wordAPI.BookAddReq) (res *wordAPI.BookAddRes, err error) {
	doc := &entity.WordBook{
		BookId:        req.BookId,
		Title:         req.Title,
		Cover:         req.Cover,
		BookOrigin:    req.BookOrigin,
		Size:          req.Size,
		Introduce:     req.Introduce,
		WordNum:       req.WordNum,
		ReciteUserNum: req.ReciteUserNum,
		OfflineData:   req.OfflineData,
		Version:       req.Version,
		Tags:          req.Tags,
	}
	doc.SetTimeValue(0)
	doc.SetTimeValue(1)

	err = service.Mgx().InsertOne(ctx, consts.CWordBooks, doc)
	if err != nil {
		g.Log().Error(ctx, "Insert error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	return &wordAPI.BookAddRes{BookId: doc.BookId}, nil
}

// QueryInfo 获取词书信息
func (c *cBookCtrl) QueryInfo(ctx context.Context, req *wordAPI.BookInfoReq) (res *wordAPI.BookInfoRes, err error) {
	qMap := g.Map{
		"bookId": req.BookId,
	}
	result, err := service.Mgx().FindOne(ctx, consts.CWordBooks, qMap, bson.M{})
	if err != nil {
		return nil, gerror.Wrap(err, "获取数据失败")
	}

	var data entity.WordBook
	if err = gconv.Struct(result, &data); err != nil {
		return nil, gerror.Wrap(err, "数据转换失败")
	}

	return &wordAPI.BookInfoRes{WordBook: data}, nil
}

// UpdateBook 更新词书
func (c *cBookCtrl) UpdateBook(ctx context.Context, req *wordAPI.BookUpdateReq) (res *wordAPI.BookUpdateRes, err error) {
	if req.BookId == "" {
		return nil, gerror.NewCode(ecode.InvalidParams, "词书ID不能为空")
	}

	updateDoc := form.NewBuilder().
		Set("title", req.Title).
		Set("cover", req.Cover).
		Set("bookOrigin", req.BookOrigin).
		Set("size", req.Size).
		Set("introduce", req.Introduce).
		Set("wordNum", req.WordNum).
		Set("reciteUserNum", req.ReciteUserNum).
		Set("offlineData", req.OfflineData).
		Set("version", req.Version).
		Set("tags", req.Tags).
		Set("updated_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(
		ctx,
		consts.CWordBooks,
		bson.M{"bookId": req.BookId},
		bson.M{"$set": updateDoc},
	)
	if err != nil {
		g.Log().Error(ctx, "Update error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}

	return &wordAPI.BookUpdateRes{}, nil
}

// DeleteBook 删除词书
func (c *cBookCtrl) DeleteBook(ctx context.Context, req *wordAPI.BookDeleteReq) (res *wordAPI.BookDeleteRes, err error) {

	updateDoc := form.NewBuilder().
		Set("deleted_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(ctx,
		consts.CWordBooks,
		bson.M{"bookId": req.BookId},
		bson.M{"$set": updateDoc},
	)

	if err != nil {
		return nil, gerror.Wrap(err, "删除数据失败")
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}
	return &wordAPI.BookDeleteRes{}, nil
}

// QueryMini 获取词书列表
func (c *cBookCtrl) QueryMini(ctx context.Context, req *wordAPI.BookMiniReq) (res *wordAPI.BookMiniRes, err error) {
	qMap := bson.M{}

	fieldsMap := bson.M{
		"bookId": 1,
		"title":  1,
	}
	result, err := service.Mgx().Find(ctx, consts.CWordBooks, qMap, fieldsMap, 0, consts.DefaultLimit, nil)

	if err != nil {
		return nil, gerror.Wrap(err, "获取数据失败")
	}
	var data []outin.BookItem
	if err = gconv.Struct(result, &data); err != nil {
		return nil, gerror.Wrap(err, "数据转换失败")
	}

	res = &wordAPI.BookMiniRes{
		Data: data,
	}

	return
}

func (c *cBookCtrl) QueryOrigin(ctx context.Context, req *wordAPI.BooksOriginReq) (res *wordAPI.BooksOriginRes, err error) {
	return
}
func (c *cBookCtrl) AddBookOrigin(ctx context.Context, req *wordAPI.BooksOriginAddReq) (res *wordAPI.BooksOriginAddRes, err error) {
	return
}
func (c *cBookCtrl) QueryTags(ctx context.Context, req *wordAPI.BooksTagsReq) (res *wordAPI.BooksTagsRes, err error) {
	return
}
func (c *cBookCtrl) AddTags(ctx context.Context, req *wordAPI.BooksTagsAddReq) (res *wordAPI.BooksTagsAddRes, err error) {

	fmt.Println(req)

	return
}
